<?php
/**
 * AuthSign
 *
 * @Description 描述
 * @Author look
 * @CreateTime 2022/2/22
 */

namespace app\common\utils;

use app\common\exception\ApiException;
use think\facade\Config;

/**
 * 请求认证sign
 */
class AuthSign {
    /**
     * 签名过期时间（单位:s）
     */
    private const SIGN_EXP = 20;
    private const SECRET_KEY = "Ry6hpr2HHrEO";

    /**
     * @param ?int $time
     * @param ?string $notify
     * @param ?string $sign
     * @param ?string $version
     * @param ?string $platform
     */
    public function __construct(
        private ?int $time,
        private ?string $notify,
        private ?string $sign,
        private ?string $version,
        private ?string $platform) {
    }

    public function checkSign():bool|ApiException {
        if (!Config::get('admin.auth_sign')) {
            return true;
        }

        if (empty($this->time) || empty($this->notify) || empty($this->version) || empty($this->platform) || empty($this->sign)) {
            throw new ApiException(...ErrorCode::SIGN_ERROR);
        }

        $this->checkSignExp();
        $data = [
            'time' => $this->time,
            'notify' => $this->notify,
            'version' => $this->version,
            'platform' => $this->platform
        ];

        ksort($data);
        $str = '';
        foreach ($data as $key => $value) {
            $str .= sprintf("%s=%s&", $key, $value);
        }
        $str = sprintf("%ssecretKey=%s", $str, self::SECRET_KEY);
        $str = md5(strtoupper($str));
        if ($str !== $this->sign) {
            throw new ApiException(ErrorCode::SIGN_ERROR[1], ErrorCode::SIGN_ERROR[0]);
        }
        return true;
    }

    private function checkSignExp():void {
        if ((time() - $this->time) > self::SIGN_EXP) {
            throw new ApiException(...ErrorCode::SIGN_ERROR);
        }
    }


    /**
     * @return int
     */
    public function getTime(): int {
        return $this->time;
    }

    /**
     * @param int $time
     */
    public function setTime(int $time): void {
        $this->time = $time;
    }

    /**
     * @return string
     */
    public function getNotify(): string {
        return $this->notify;
    }

    /**
     * @param string $notify
     */
    public function setNotify(string $notify): void {
        $this->notify = $notify;
    }

    /**
     * @return string
     */
    public function getSign(): string {
        return $this->sign;
    }

    /**
     * @param string $sign
     */
    public function setSign(string $sign): void {
        $this->sign = $sign;
    }

    /**
     * @return string
     */
    public function getVersion(): string {
        return $this->version;
    }

    /**
     * @param string $version
     */
    public function setVersion(string $version): void {
        $this->version = $version;
    }

    /**
     * @return string
     */
    public function getPlatform(): string {
        return $this->platform;
    }

    /**
     * @param string $platform
     */
    public function setPlatform(string $platform): void {
        $this->platform = $platform;
    }

}